/*
 * Symtable.cpp
 *
 *  Created on: 08.10.2010
 *      Author: Marcel Wenzel
 */

#include "Symtable.h"
#include <stdlib.h>

Symtable::Symtable(int size) {
	this->size = size;
	this->hashtable = (SymtableEntry**)malloc(size);
}

Symtable::Symtable() {
	this->size = 100;
	this->hashtable = (SymtableEntry**)malloc(size);
}

Symtable::~Symtable() {
	free(hashtable);
}

int Symtable::insert(Token* entry) {
	int key = hash(entry);
	setToNextFreeCell(key, entry);
	return key;
}

void Symtable::setToNextFreeCell(int key, Token* token) {
	SymtableEntry* entry = new SymtableEntry(token);
	if(this->hashtable[key] == 0x00) {
		this->hashtable[key] = entry;
	} else {
		SymtableEntry* lastEntry = isAlreadyInsertOrGetLastPos(key, entry);
		if(lastEntry != 0x00) {
			lastEntry->setNext(entry);
		}
	}

}

SymtableEntry* Symtable::isAlreadyInsertOrGetLastPos(int key, SymtableEntry* entry) {
	SymtableEntry* currentEntry = this->hashtable[key];
	SymtableEntry* nextEntry = 0x00;
	do {
		if(currentEntry->equals(entry)) {
			return 0x00;
		}
		currentEntry = nextEntry;
		nextEntry = currentEntry->getNext();
	}
	while(!currentEntry->hasNext());
	return currentEntry;
}

int Symtable::hash(Token* entry) {
	if (entry == 0x00) {
		return -1;
	} else {
		int sum = 0;
		int anzahlZeichen = 0;
		char* lexem = entry->lexem;

		while(*lexem) {
			sum = sum + getDecimalAsciiValue(*lexem);
			lexem++;
			anzahlZeichen++;
		}

		return (sum / anzahlZeichen) % this->size;
	}
}

int Symtable::getDecimalAsciiValue(const char &sign) {
	char startAscii = 0x21;		// 0x21 entspricht "!".
	int currentDecimalValue = 33;

	for (int i=31; i<125; i++) {
		if (startAscii == sign) {
			return currentDecimalValue;
		}

		startAscii++;
		currentDecimalValue++;
	}

	return 0;
}
